package com.sm.healthy.device;


import com.sm.healthy.device.interfaces.Up_ECGListener;
import com.sm.healthy.device.interfaces.Up_NBPListener;
import com.sm.healthy.device.interfaces.Up_SPO2Listener;

/**
 * Created by shenmai8 on 2018/4/21.
 * 使用方法 ：创建一个MedicalProtocol（）对象 设置相关的监听器
 */

public class MedicalProtocol implements Command.ResolveCommandListener {
    private final String TAG = getClass().getSimpleName();
    private final Command command;
    private Up_ECGListener up_ecgListener;
    private Up_SPO2Listener spo2Listener = null;
    private Up_NBPListener nbpListener;

    public static final byte ACTION_CMD_NBP_END = 0;
    public static final byte ACTION_CMD_NBP_START = 1;
    public static final byte ACTION_CMD_NBP_CAL = 2;
    public static final byte ACTION_CMD_NBP_PERIOD = 3;
    public static final byte ACTION_CMD_NBP_RESET = 4;
    public static final byte ACTION_CMD_NBP_ADJUST = 5;
    public static final byte ACTION_CMD_NBP_POLL_STATE = 6;
    public static final byte ACTION_CMD_NBP_RESULT = 7;

    private int count;
    private long time;
    static Command pCommand = null;


    public MedicalProtocol() {
        command = new Command();
        pCommand = command;
        command.setResolveCommandListener(this);
        time = System.currentTimeMillis();

    }

    synchronized public void Resolve(byte[] data, int offset, int length) {
        command.Resolve(data, offset, length);
    }

    public static void MyResolve(byte[] data, int offset, int length) {
        if (null != pCommand)
            pCommand.Resolve(data, offset, length);
    }

    /**
     * 启动/中止 血压测量相关动作
     *
     * @param action 1-启动一次手动或自动测量 <br/>
     *               2-静态压模式，NBP校准 <br/>
     *               3-测量周期设置，默认为1分钟 <br/>
     *               4-复位 <br/>
     *               5-压力校正 <br/>
     *               6-查询状态
     *               0-中止测量，包括手动测量、自动测量、STAT测量、漏气检测、校准
     * @param param  对应压力校正的压力值，其他动作默认为-1
     */
    public byte[] NBP_Action(int action, int param) {
        int cmd;
        byte[] data = new byte[]{};
        switch (action) {
            case ACTION_CMD_NBP_END:
                cmd = MedicalDefine.CMD_NBP_END;
                break;
            case ACTION_CMD_NBP_START:
                cmd = MedicalDefine.CMD_NBP_START;
                break;
            case ACTION_CMD_NBP_CAL:
                cmd = MedicalDefine.CMD_NBP_CAL;
                break;
            case ACTION_CMD_NBP_PERIOD:
                cmd = MedicalDefine.CMD_NBP_PERIOD;
                data = new byte[]{1}; //默认，设置测量周期为1分钟
                break;
            case ACTION_CMD_NBP_RESET:
                cmd = MedicalDefine.CMD_NBP_RESET;
                break;
            case ACTION_CMD_NBP_ADJUST:
                cmd = MedicalDefine.CMD_NBP_ADJUST;
                byte param1 = (byte) 0x00;
                if (param > 255) {
                    param1 = (byte) 0x01;
                }
                data = new byte[]{param1, (byte) param};
                break;
            case ACTION_CMD_NBP_POLL_STATE:
                cmd = MedicalDefine.CMD_NBP_POLL_STATE;
                break;
            case ACTION_CMD_NBP_RESULT:
                cmd = MedicalDefine.CMD_NBP_GET_RESULT;
                break;
            default:
                return null;
        }

        return Command.Create(cmd, data);
    }

    /**
     * 解析指令方法
     */
    @Override
    synchronized public void ResolveCommandHandle(int cmd, byte[] data) {
        switch (cmd) {

            case MedicalDefine.ID_SELFTEST:
                resiveSelfTest(cmd, data);
                break;
            // 获得serialNumber
            case MedicalDefine.ID_READ_SN:
//                resolveReadSN(data);
                break;
            case MedicalDefine.ID_CMD_ACK:
//                resolveCmdAck(data);
                break;
            // [start] 心电
            case MedicalDefine.ID_ECGWAVE:
                resolveECG_Wave(data);
                break;
            case MedicalDefine.ID_LEAD_STS:
                resolveECG_Lead_STS(data);
                break;
            case MedicalDefine.ID_HR:
                resolveECG_HR(data);
                break;
            case MedicalDefine.ID_HR_STATUS:
                resolveECG_HR_STATUS(data[0]);
                break;
            // [end]心电
            // [start] 血氧
            case MedicalDefine.ID_SPO2_WAVE:
                resolveSPO2_Wave(data);
                break;
            case MedicalDefine.ID_SPO2_PR:
                resolveSPO2_PR(data);
                break;
            // [end]血氧
            // [start] 血压
            case MedicalDefine.ID_NBP_CUFPRE:   //袖带压
                resolveNBP_CuffPressure(data);
                break;
            case MedicalDefine.ID_NBP_END:      //血压测量结束
                resolveNBP_End(data);
                break;
            case MedicalDefine.ID_NBP_RESULT1:
                resolveNBP_Result1(data);
                break;
            case MedicalDefine.ID_NBP_RESULT2:
//                resolveNBP_Result2(data);
                break;
            case MedicalDefine.ID_NBP_STS:   //血压状态
                resolveNBP_State(data);
                break;
            // [end]血压
            // [start] 体温
            case MedicalDefine.ID_TEMP:
//                resolveTMEP(data);
                break;
            // [end]
            case MedicalDefine.ID_RSP_ZXFE_SOFTWARE_START:
//                resolveRspStartDeviceDetection(data);
                break;
            case MedicalDefine.ID_ZXFE_BATTERY_STATUS:
//                resolveDeviceBattery(data);
                break;
            default:
                break;
        }
    }

    private void resolveECG_HR_STATUS(byte data) {
        String hrErrorMsg = getHRErrorMsg(data);
        if (up_ecgListener != null)
            up_ecgListener.onECG_HeartRateStatus(hrErrorMsg);

    }

    private void resiveSelfTest(int cmd, byte[] data) {
    }


    // [start] --------------心电-------------------
    synchronized private void resolveECG_Wave(byte[] data) {
        if (up_ecgListener == null)
            return;

        int data1 = data[0] & 0x0F;
        int data2 = data[1] & 0xFF;
        int wave = (data1 << 8) + (data2 < 0 ? (data2 + 256) : data2);
//        buff.add(wave);
        //处理波形
        up_ecgListener.onECG_Wave(wave, false);
    }


    private void resolveECG_HR(byte[] data) {
        if (up_ecgListener != null) {
            int hr = ((data[0] & 0xFF) << 8) + (data[1] & 0xFF);
            up_ecgListener.onECG_HeartRate(hr);
        }
    }

    private void resolveECG_Lead_STS(byte[] data) {
        if (up_ecgListener != null) {
            up_ecgListener.onECG_Lead_STS(data[0]);
        }
    }
    //    [end]

    // [start] ------------------血氧----------------------

    private void resolveSPO2_Wave(byte[] data) {

        if (spo2Listener == null)
            return;
        int wave;
        if (data[0] < 0)
            wave = data[0] + 256;
        else
            wave = data[0];

        int status = (data[1] & 0x10) >> 4;
        spo2Listener.onSPO2_Wave(wave, status);
    }

    private void resolveSPO2_PR(byte[] data) {
        if (spo2Listener == null)
            return;
        int pulseRate = 0;
        int spo2 = 0;
        int data1 = (data[1] & 0xFF) << 8;
        int data2 = data[2] & 0xFF;
        pulseRate = data1 + data2;
        if (data[3] >= 0 && data[3] <= 100)
            spo2 = data[3];
        spo2Listener.onSPO2_PR(spo2, pulseRate);
    }

    // [end]


    /**
     * 解析血压之袖带压<br/>
     * 该数据包每秒发送5次
     */
    private void resolveNBP_CuffPressure(byte[] data) {
        short val = 0;
        if (data[0] > 0x00) {
            val = (short) (256 + data[1]);
        } else if (data[1] < 0) {
            val = (short) (256 + data[1]);
        } else {
            val = data[1];
        }
        nbpListener.onNBP_CuffPressure(val);
    }

    private void resolveNBP_Result1(byte[] data) {
        if (nbpListener == null)
            return;
        int systolic, diastolic, count;
        if (data[0] > 0x00) {
            systolic = (short) (256 + data[1]);
        } else if (data[1] < 0) {
            systolic = (short) (256 + data[1]);
        } else {
            systolic = data[1];
        }
        if (data[2] > 0x00) {
            diastolic = (short) (256 + data[3]);
        } else if (data[3] < 0) {
            diastolic = (short) (256 + data[3]);
        } else {
            diastolic = data[3];
        }
        if (data[4] > 0x00) {
            count = (short) (256 + data[5]);
        } else if (data[5] < 0) {
            count = (short) (256 + data[5]);
        } else {
            count = data[5];
        }
        nbpListener.onNBP_Result(systolic, diastolic, count);
    }

//    private void resolveNBP_Result2( byte[] data) {
//        if (nbpListener == null)
//            return;
//        nbpListener.onNBP_Result(pulseRate);
//    }

    private void resolveNBP_End(byte[] data) {
        if (nbpListener == null)
            return;
        nbpListener.onNBP_End(data[0]);
    }

    private void resolveNBP_State(byte[] data) {
        if (nbpListener != null) {
            nbpListener.onNBP_State(data);
        }

    }

    public String getErrorMsg(int error) {
        switch (error) {
            case 0:
                return "无错误";
            case 1:
                return "袖带过松";
            case 2:
                return "漏气";
            case 3:
                return "气压错误";
            case 4:
                return "弱信号";
            case 5:
                return "弱信号";
            case 6:
                return "过分运动";
            case 7:
                return "过压";
            case 8:
                return "信号饱和";
            case 9:
                return "漏气检测失败";
            case 10:
                return "系统错误";
            case 11:
                return "超时";
            default:
                return "  ";
        }
    }

    public String getHRErrorMsg(int error) {
        switch (error) {
            case 0:
                return "正常";
            case 1:
                return "停搏";
            case 2:
                return "室颤或室速";
            case 3:
                return "R on T";
            case 4:
                return "三个或四个连发室早";
            case 5:
                return "二连发室早";
            case 6:
                return "单个室早";
            case 7:
                return "室早二联律";
            case 8:
                return "室早三联律";
            case 9:
                return "心动过速";
            case 10:
                return "心动过缓";
            case 11:
                return "起搏器未俘获";
            case 12:
                return "起搏器未起搏";
            case 13:
                return "漏搏";
            case 14:
                return "正在学习";
            case 15:
                return "正常心律";
            case 16:
                return "噪声信号";
            case 17:
                return "信号幅度过小";
            default:
                return "  ";
        }
    }


    public void setUp_ecgListener(Up_ECGListener up_ecgListener) {
        this.up_ecgListener = up_ecgListener;
    }

    public void setSpo2Listener(Up_SPO2Listener spo2Listener) {
        this.spo2Listener = spo2Listener;
    }

    public void setNbpListener(Up_NBPListener nbpListener) {
        this.nbpListener = nbpListener;
    }
}
